package com.thb.pay.core.interceptor;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.serializer.SerializerFeature;
import com.thb.pay.core.annotation.OperationLog;
import com.thb.pay.core.holder.OperatorLogContextHolder;
import com.thb.pay.core.logs.domain.OperationLogEntity;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.web.method.HandlerMethod;
import org.springframework.web.servlet.HandlerInterceptor;
import org.springframework.web.servlet.ModelAndView;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.lang.reflect.Method;
import java.util.Date;

/**
 * 日志记录拦截器  在登入拦截后做拦截 [主要是拦截登入后的详细操作]
 */

public abstract class AbstractOperationLogInterceptor implements HandlerInterceptor {
    public final static Integer OPERATOR_PLATEFORM_MANAGE = 1;    // 运营系统
    public final static Integer OPERATOR_PLATEFORM_MECHANT = 2;    // 商户系统
    public final static Integer OPERATOR_PLATEFORM_AGENT = 3;    // 代理商系统

    protected static final Logger logger = LoggerFactory.getLogger(AbstractOperationLogInterceptor.class);

    private static final String LOG_KEY = "logBean";

    public abstract void insertOperatorLog(HttpServletRequest request, HttpServletResponse response, OperationLogEntity operationLog);

    /**
     * @return
     * @方法名称
     * @功能描述 实现日志记录的操作平台
     * @作者: lucky
     * @创建时间: 17:58 2019/10/11
     * @版本 v1.01
     **/
    public abstract Integer operatorPlate();

    @Override
    public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
        // 如果不是映射到方法直接通过
        if (!(handler instanceof HandlerMethod)) {
            return true;
        }
        HandlerMethod handlerMethod = (HandlerMethod) handler;
        Method method = handlerMethod.getMethod();

        if (method.isAnnotationPresent(OperationLog.class)) {
            OperationLog required = method.getAnnotation(OperationLog.class);
            //包名 方法名
            String methodName = method.getName();

            //获取请求参数信息
            String paramData = JSON.toJSONString(request.getParameterMap(), SerializerFeature.DisableCircularReferenceDetect, SerializerFeature.WriteMapNullValue);
            final OperationLogEntity operationLog = OperationLogEntity.builder()
                    .type(operatorPlate())//操作平台
                    .optReqParam(required.value())//注解备注
                    .optReqParam(paramData)//请求参数
                    .methodName(methodName)
                    .methodRemark(required.value())
                    .build();
            operationLog.setCreateTime(new Date());
            //为后续进行处理操作
            OperatorLogContextHolder.set(LOG_KEY, operationLog);
        }

        return true;
    }

    @Override
    public void postHandle(HttpServletRequest request,
                           HttpServletResponse response,
                           Object handler, ModelAndView modelAndView) throws Exception {

    }

    @Override
    public void afterCompletion(HttpServletRequest request,
                                HttpServletResponse response,
                                Object handler, Exception e) throws Exception {
        try {
            HandlerMethod handlerMethod = (HandlerMethod) handler;
            Method method = handlerMethod.getMethod();
            if (method.isAnnotationPresent(OperationLog.class)) {
                OperationLogEntity operationLog = OperatorLogContextHolder.get(LOG_KEY, OperationLogEntity.class);
                if (operationLog != null) {
                    operationLog.setOptResInfo("");
                    operationLog.setUpdateTime(new Date());
                    operationLog.setTimeConsuming(Integer.valueOf(String.valueOf((new Date().getTime() - operationLog.getCreateTime().getTime()))));
                    insertOperatorLog(request, response, operationLog);
                    OperatorLogContextHolder.delete(LOG_KEY);
                }
            }

        } catch (Exception ex) {
            logger.warn("operator.log.error", ex);
        }
    }

}